//
// Created by wxd on 2025/8/25.
//

#include "generator_id.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <chrono>

// 初始化静态成员
thread_local std::unique_ptr<IDGenerator::AtomicIDGenerator> IDGenerator::threadLocalGenerator = nullptr;
std::atomic<uint16_t> IDGenerator::nextInstanceId(0);

IDGenerator::IDGenerator()
    : instanceId(nextInstanceId.fetch_add(1, std::memory_order_relaxed)),
      totalGenerated(0), lastSecondCount(0) {

    lastResetTime = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now().time_since_epoch()).count();

    // 初始化默认前缀映射
    prefixMap = {
        {IDPrefix::RENDER_OBJECT, "RENDER_OBJECT"},
        {IDPrefix::MESH, "MESH"},
        {IDPrefix::MATERIAL, "MATERIAL"},
        {IDPrefix::SHADER, "SHADER"},
        {IDPrefix::TEXTURE, "TEXTURE"},
        {IDPrefix::CAMERA, "CAMERA"},
        {IDPrefix::LIGHT, "LIGHT"},
        {IDPrefix::FRAME, "FRAME"},
        {IDPrefix::EVENT, "EVENT"},
        {IDPrefix::GEOMETRY, "GEOMETRY"},
        {IDPrefix::USER_DEFINED, "USER_DEFINED"}
    };
}

IDGenerator& IDGenerator::getInstance() {
    static IDGenerator instance;
    return instance;
}

TraceID IDGenerator::generateRaw() {
    // 延迟初始化线程局部生成器
    if (!threadLocalGenerator) {
        threadLocalGenerator = std::make_unique<AtomicIDGenerator>(
            getInstance().instanceId);
    }

    TraceID id = threadLocalGenerator->generate();
    getInstance().updateStatistics();
    return id;
}

std::string IDGenerator::generateString(IDPrefix prefix) {
    TraceID rawId = generateRaw();

    std::lock_guard<std::mutex> lock(prefixMutex);
    auto it = prefixMap.find(prefix);
    std::string prefixStr = (it != prefixMap.end()) ? it->second : "UNKN";

    std::stringstream ss;
    ss << prefixStr << "_" << std::hex << std::setw(16) << std::setfill('0') << rawId;
    return ss.str();
}

std::string IDGenerator::generateCustomString(const std::string& customPrefix) {
    TraceID rawId = generateRaw();

    std::stringstream ss;
    ss << customPrefix << "_" << std::hex << std::setw(16) << std::setfill('0') << rawId;
    return ss.str();
}

void IDGenerator::registerPrefix(IDPrefix prefix, const std::string& prefixStr) {
    std::lock_guard<std::mutex> lock(prefixMutex);
    prefixMap[prefix] = prefixStr;
}

void IDGenerator::parseID(TraceID id, uint64_t& timestamp, uint16_t& instanceId, uint16_t& sequence) {
    timestamp = (id >> 22) & 0x3FFFFFFFFFF;
    instanceId = (id >> 12) & 0x3FF;
    sequence = id & 0xFFF;
}

IDGenerator::Statistics IDGenerator::getStatistics() const {
    std::lock_guard<std::mutex> lock(statsMutex);
    return {totalGenerated, lastSecondCount, lastResetTime};
}

void IDGenerator::resetStatistics() {
    std::lock_guard<std::mutex> lock(statsMutex);
    totalGenerated = 0;
    lastSecondCount = 0;
    lastResetTime = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now().time_since_epoch()).count();
}

void IDGenerator::updateStatistics() {
    std::lock_guard<std::mutex> lock(statsMutex);
    totalGenerated++;

    uint64_t currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now().time_since_epoch()).count();

    // 每秒重置计数
    if (currentTime - lastResetTime >= 1000) {
        lastSecondCount = totalGenerated;
        lastResetTime = currentTime;
    }
}

// TraceScope 实现
TraceScope::TraceScope(const std::string& funcName, IDPrefix prefix)
    : functionName(funcName), startTime(std::chrono::steady_clock::now()) {

    traceId = IDGenerator::getInstance().generateString(prefix);

    std::cout << "[TRACE_START] " << traceId << " - " << functionName << std::endl;
}

TraceScope::~TraceScope() {
    auto endTime = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);

    std::cout << "[TRACE_END] " << traceId << " - " << functionName
              << " - Duration: " << duration.count() << "μs" << std::endl;
}

void TraceScope::addTag(const std::string& key, const std::string& value) {
    std::cout << "[TRACE_TAG] " << traceId << " - " << key << "=" << value << std::endl;
}